package me.riverslob.test.esper.plugin.esperio.rpc;

import com.espertech.esper.plugin.PluginLoader;
import com.espertech.esper.plugin.PluginLoaderInitContext;
import com.espertech.esperio.http.EsperIOHTTPAdapter;
import com.espertech.esperio.http.config.ConfigurationHTTPAdapter;
import me.riverslob.test.esper.plugin.esperio.rpc.config.ConfigurationRPCAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.URL;

/**
 * <br/>Created on 13-10-12 上午10:44
 *
 * @author 郑治明（zm.zheng@zhuche.com）
 * @since 3.2.2
 */
public class EsperIORPCAdapterPlugin implements PluginLoader {
    private static final Logger log = LoggerFactory.getLogger(EsperIORPCAdapterPlugin.class);

    private static final String ESPERIO_RPC_CONFIG_FILE = "esperio.rpc.configuration.file";

    private EsperIORPCAdapter httpadapter;
    private PluginLoaderInitContext context;

    public void init(PluginLoaderInitContext context)
    {
        this.context = context;
    }

    public void postInitialize()
    {
        ConfigurationRPCAdapter adapterConfig;
        if (context.getConfigXml() != null) {
            adapterConfig = fromXml(context.getConfigXml());
        }
        else {
            adapterConfig = fromExternalFile();
        }

        log.info("");
        log.info("Starting RPC Adapter");
        httpadapter = new EsperIORPCAdapter(adapterConfig, context.getEpServiceProvider().getURI());
        httpadapter.start();
    }

    public void destroy()
    {
        if (httpadapter != null)
        {
            httpadapter.destroy();
        }
        httpadapter = null;
    }

    private ConfigurationRPCAdapter fromXml(String xml) {
        ConfigurationRPCAdapter adapter = new ConfigurationRPCAdapter();
        return adapter.configureFromString(xml);
    }

    private ConfigurationRPCAdapter fromExternalFile() {

        // obtain config file name
        String configFile = context.getProperties().getProperty(ESPERIO_RPC_CONFIG_FILE);
        if (configFile == null)
        {
            String message = "Required initialization property '" + ESPERIO_RPC_CONFIG_FILE + "' is not provided";
            log.error(message);
            throw new RuntimeException(message);
        }

        // resolve config file
        URL urlConfigFile;
        try
        {
            urlConfigFile = resolveURL(configFile);
        }
        catch (Exception ex)
        {
            String message = "Error resolving config file from classpath or as a URL: " + ex.getMessage();
            log.error(message, ex);
            throw new RuntimeException(message, ex);
        }

        if (urlConfigFile == null)
        {
            String message = "Configuration file could not be resolved from '" + urlConfigFile + "'";
            log.error(message);
            throw new RuntimeException(message);
        }

        // parse config file
        ConfigurationRPCAdapter config = new ConfigurationRPCAdapter();
        try
        {
            config.configure(urlConfigFile);
        }
        catch (RuntimeException ex)
        {
            String message = "Configuration file read error for config file '" + urlConfigFile + "': " + ex.getMessage();
            log.error(message, ex);
            throw new RuntimeException(message, ex);
        }

        return config;
    }

    private URL resolveURL(String config) throws Exception
    {
        URL url = this.getClass().getClassLoader().getResource(config);
        if (url != null)
        {
            return url;
        }

        url = Thread.currentThread().getContextClassLoader().getResource(config);
        if (url != null)
        {
            return url;
        }

        File file = new File(config);
        if (!file.isAbsolute()) {
            String espereeBase = System.getProperty("esperee.base");
            file = new File(espereeBase, config);
        }
        if (file.exists()) {
            return file.toURI().toURL();
        }

        return new URL(config);
    }
}
